<?php
/**
 * Created by PhpStorm.
 * User: Steven
 * Date: 2017/6/30
 */

namespace app\pay\controller;


use app\classes\model\ClassModel;
use app\financial\model\OrderModel;
use cmf\controller\HomeBaseController;
use cmf\controller\UserBaseController;
use think\Db;
use think\Log;

class WxpayController extends HomeBaseController
{
    public function _initialize()
    {
        parent::_initialize();
        //载入支付类库
        import('pay.wxpay.lib.WxPayPubHelper', EXTEND_PATH);
        import('pay.wxpay.lib.WxPayApi', EXTEND_PATH);
        import('pay.wxpay.lib.WxPayNotify', EXTEND_PATH);

        import('pay.wxpay.unit.JsApiPay', EXTEND_PATH);
        import('pay.wxpay.unit.MicroPay', EXTEND_PATH);
        import('pay.wxpay.unit.NativePay', EXTEND_PATH);
        import('pay.wxpay.unit.phpqrcode.phpqrcode', EXTEND_PATH);
    }

    /**
     * 微信支付接口
     * @return mixed
     */
    public function index()
    {
        //检查登录
        $this->checkUserLogin();

        $param = $this->request->param();
        Log::write('Wxpay_result0='.print_r($param,true));
        if(isset($param['order_id']) && !empty($param['order_id'])){
            $order_id = base64_decode($param['order_id']);
            //把当前订单存入session
            $_SESSION['cur_order_id'] = $order_id;
        }

        if(!isset($_SESSION['student_id']) || empty($_SESSION['student_id'])){
            //跳转到订单页
            $this->error('参数错误','order/FrontOrder/index');
        }

        //学生
        $student_id = $_SESSION['student_id'];

        if($_SESSION['cur_order_id']){
            $order_id = $_SESSION['cur_order_id'];
        }else{
            $order_id = 0;
            $this->error('订单编号不能为空','order/FrontOrder/index');
        }

        $where = [
            'o.order_id' => ['=', $order_id],
            'o.student_id' => ['=', $student_id],
        ];
        //获取订单
        $order_mdl = new OrderModel();
        $order = $order_mdl->getOrderByField($where);
        if(count($order) <= 0){
            //没有该订单
            $this->error('没有该订单','order/FrontOrder/index');
        }
        if($order['cancel_time'] < time()){
            //订单已过期，修改订单状态,同时释放座位，优惠返回等相关操作
            $update_data = [
                'id' => $order['id'],
                'order_status' => 3,//已取消
                'update_time' => time(),
            ];
            //修改订单
            $order_mdl->editOrder($update_data);

            //释放座位
            $class_mdl = new ClassModel();
            $class_mdl->releaseSeat($order['class_id'], $order['student_id'], $this->front_shop_id);

            //释放优惠
            $award_where = [
                'student_id' => $order['student_id'],
                'order_id' => $order['id'],
            ];
            $seat = Db::name('award_order')->where($award_where)->find();
            if(count($seat) > 0) {
                Db::name('award_order')->where($award_where)->delete();
            }

            $this->error('该订单已过期','order/FrontOrder/index');
        }

        //扫码支付url
        $code_url = '';
        //公众号支付数据
        $jsApiParameters = '';

        //转化订单实际支付金额以分为单位
        $amount = ($order['pay_amount'] * 100);
        $total_fee = $amount;
        $out_trade_no = $order['order_id'];
        $body = '学员【'.$order['student_name'].'】报班【'.$order['school_name'].'-'.$order['class_name'].'-'.$order['course_name'].'】';

        //统一支付接口
        $unifiedOrder = new \UnifiedOrder_pub();
        //设置统一支付接口参数
        $unifiedOrder->setParameter("body",$body);//商品描述
        $unifiedOrder->setParameter("total_fee",$total_fee); //总金额
        $unifiedOrder->setParameter("out_trade_no","$out_trade_no");//商户订单号
        $unifiedOrder->setParameter("notify_url", \WxPayConfig::NOTIFY_URL);//异步通知地址

        //判断是否为微信浏览器
        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {
            Log::write('Wxpay_result=公众号支付');
            //公众号支付
            $pay_type = 'jsapi';

            $jsApi_obj = new \JsApi_pub();
            if (!isset($_GET['code'])){
                Log::write('Wxpay_result1=no_code');

                //触发微信返回code码
                $url = $jsApi_obj->createOauthUrlForCode(\WxPayConfig::JS_API_CALL_URL);
                header("Location: $url");
                exit();
            }else{
                //获取code码，以获取openid
                $code = $_GET['code'];
                $jsApi_obj->setCode($code);
                $openId = $jsApi_obj->getOpenid();
            }
            //用户标识
            $unifiedOrder->setParameter("openid",$openId);
            $unifiedOrder->setParameter("trade_type","JSAPI");
            //预交易码
            $prepay_id = $unifiedOrder->getPrepayId();
            $jsApi_obj->setPrepayId($prepay_id);
            $jsApiParameters = $jsApi_obj->getParameters();
            Log::write('Wxpay_result-jsapi2='.print_r($jsApiParameters,true));

        }else{
            Log::write('Wxpay_result=扫码支付');
            //扫码支付
            $pay_type = 'native';
            $unifiedOrder->setParameter("trade_type","NATIVE");

            //非必填参数，商户可根据实际情况选填
            //$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号
            //$unifiedOrder->setParameter("device_info","XXXX");//设备号
            //$unifiedOrder->setParameter("attach","XXXX");//附加数据
            //$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
            //$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间
            //$unifiedOrder->setParameter("goods_tag","");//商品标记
            //$unifiedOrder->setParameter("product_id","XXXX");//商品ID

            //获取统一支付接口结果
            $unifiedOrderResult = $unifiedOrder->getResult();
            Log::write('Wxpay_result4='.print_r($unifiedOrderResult,true));

            //商户根据实际情况设置相应的处理流程
            if($unifiedOrderResult["return_code"] == "FAIL"){
                //商户自行增加处理流程
                echo "通信出错：".$unifiedOrderResult['return_msg']."<br>";
            }
            elseif($unifiedOrderResult["result_code"] == "FAIL"){
                //支付交易失败
                echo "错误代码：".$unifiedOrderResult['err_code']."<br>";
                echo "错误代码描述：".$unifiedOrderResult['err_code_des']."<br>";
            }
            elseif($unifiedOrderResult["result_code"] == "SUCCESS" && $unifiedOrderResult["code_url"] != NULL){
                //扫码支付code_url
                $code_url = $unifiedOrderResult["code_url"];
            }
        }

        $this->assign('out_trade_no',$out_trade_no);
        $this->assign('code_url',$code_url);
        $this->assign('pay_type',$pay_type);
        $this->assign('pay_total',$order['pay_amount']);
        $this->assign('jsApiParam',$jsApiParameters);

        return $this->fetch();
    }

    /**
     *微信扫码支付二维码图片
     */
    public function wxImage()
    {
        $img_url = $this->request->param('data');
        //解码URL
        $img_url = urldecode($img_url);
        \QRcode::png($img_url);
    }


    /**
     *微信公众号支付
     */
    public function doJsapi()
    {
        Log::write('Wxpay_result9=doJsapi');
        //获取用户openid
        $tools = new \JsApiPay();
        //统一下单
        $input = new \WxPayUnifiedOrder();
        //商品描述
        $input->SetBody('test');
        //附加数据，可以添加自己需要的数据，微信回异步回调时会附加这个数据
        $input->SetAttach('xxx');
        //商户订单号
        $out_trade_no = \WxPayConfig::MCHID.date("YmdHis");
        $input->SetOut_trade_no($out_trade_no);
        //总金额,订单总金额，只能为整数,单位为分
        $input->SetTotal_fee(1);
        //交易起始时间
        $input->SetTime_start(date("YmdHis"));
        //交易结束时间
        $input->SetTime_expire(date("YmdHis", time() + 600));
        //商品标记
        $input->SetGoods_tag($this->_order_goods_tag);
        //通知地址,接收微信支付异步通知回调地址 SITE_URL=http://test.paywechat.com/Charge
        $input->SetNotify_url(\WxPayConfig::NOTIFY_URL);
        //交易类型
        $input->SetTrade_type("JSAPI");

        $openId = $tools->GetOpenid();
        $input->SetOpenid($openId);

        $order = \WxPayApi::unifiedOrder($input);
        $jsApiParameters = $tools->GetJsApiParameters($order);
        //获取共享收货地址js函数参数
        $editAddress = $tools->GetEditAddressParameters();

        $this->assign('openId',$openId);
        $this->assign('jsApiParam',$jsApiParameters);
        $this->assign('editAddress',$editAddress);
        return $this->fetch('pay/wxpay/index');
    }

    /**
     *异步接受通知
     */
    public function notify()
    {
        //记录回调信息
        $log_file = CMF_ROOT."public/wxpay_notify.log";
        $notifyData = file_get_contents("php://input");
        log_result($log_file, "【微信支付notify通知】".":\n".$notifyData."\n");

        //获取异步回调信息
        $notifyInfo = file_get_contents("php://input");
        //使用通用通知接口
        $notify = new \Notify_pub($config=[]);
        //存储微信的回调
//        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $xml = $notifyInfo;
        $notify->saveData($xml);

        //验证签名，并回应微信
        //对后台通知交互时，如果微信收到商户的应答不是成功或超时，微信认为通知失败，
        //微信会定期重新发起通知（如30分钟共8次）
        if($notify->checkSign() == FALSE){
            log_result($log_file, "【签名验证失败】".":\n".$xml."\n");

            $notify->setReturnParameter("return_code","FAIL");//返回状态码
            $notify->setReturnParameter("return_msg","签名失败");//返回信息
        }else{
            //设置返回码
            $notify->setReturnParameter("return_code","SUCCESS");
            $notify->setReturnParameter("return_msg","OK");
        }

        $returnXml = $notify->returnXml();
        log_result($log_file, "【同步通知】".":\n".$returnXml."\n");
        ob_clean();
        echo $returnXml;

        //验证签名，并回应微信
        //对后台通知交互时，如果微信收到商户的应答不是成功或超时，微信认为通知失败，
        //微信会定期重新发起通知（如30分钟共8次）
        if($notify->checkSign() == TRUE){
            if ($notify->data["return_code"] == "FAIL")
            {
                log_result($log_file, "【通信出错】".":\n".$xml."\n");
            }
            elseif($notify->data["result_code"] == "FAIL")
            {
                log_result($log_file, "【业务出错】".":\n".$xml."\n");
            }
            else{
                //此处应该更新一下订单状态，商户自行增删操作
                $result = $this->changeOrder($notify->getData());
                log_result($log_file, "【修改订单返回值】".":\n".$result."\n");
                switch ($result){
                    case 1:
                        $msg = '订单号为空';
                        break;
                    case 2:
                        $msg = '没有该订单';
                        break;
                    case 3:
                        $msg = '该订单不是待支付状态';
                        break;
                    case 4:
                        $msg = '修改订单状态失败';
                        break;
                    default:
                        $msg = '成功修改订单状态为已支付';
                        break;
                }
                log_result($log_file, "【支付信息】".":".$msg."\n");
            }
            echo "SUCCESS";
        }
    }

    /**
     * 公众号支付成功后修改订单
     * @return \think\response\Json
     */
    public function jsApiOrder()
    {
        $param = $this->request->post();
        if (!isset($param['code']) || empty($param['code'])) {
            $json_data = [
                'code' => 0,
                'msg' => '订单号不能为空',
                'data' => []
            ];
            return json($json_data);
        }

        //获取订单
        $order_data = [
            'shop_id' => $this->front_shop_id,
            'order_id' => trim($param['code']),
        ];
        $order = Db::name('order')->where($order_data)->find();
        if(count($order) <= 0){
            $json_data = [
                'code' => 0,
                'msg' => '订单不存在',
                'data' => []
            ];
            return json($json_data);
        }else{
            //检查订单是否已支付
            if($order['order_status'] == 0){
                $json_data = [
                    'code' => 0,
                    'msg' => '订单未支付',
                    'data' => []
                ];
                return json($json_data);
            }else{
                $json_data = [
                    'code' => 1,
                    'msg' => 'success',
                    'data' => url('order/FrontOrder/index',array('status'=>1))
                ];
                return json($json_data);
            }
        }
    }

    /**
     * 检查扫码支付订单是否已支付
     * @return \think\response\Json
     */
    public function checkOrder()
    {
        $param = $this->request->post();
        if (!isset($param['code']) || empty($param['code'])) {
            $json_data = [
                'code' => 0,
                'msg' => '订单号不能为空',
                'data' => []
            ];
            return json($json_data);
        }

        //获取订单
        $order_data = [
            'shop_id' => $this->front_shop_id,
            'order_id' => trim($param['code']),
        ];

        $order = Db::name('order')->where($order_data)->find();
        if(count($order) <= 0){
            $json_data = [
                'code' => 0,
                'msg' => '订单不存在',
                'data' => []
            ];
            return json($json_data);
        }else{
            //检查订单是否已支付
            if($order['order_status'] == 0){
                $json_data = [
                    'code' => 0,
                    'msg' => '订单未支付',
                    'data' => []
                ];
                return json($json_data);
            }else{
                $json_data = [
                    'code' => 1,
                    'msg' => 'success',
                    'data' => url('order/FrontOrder/index',array('status'=>1),true,true)
                ];
                return json($json_data);
            }
        }
    }

    /**
     * 支付成功后修改订单
     * @param array $parameter
     * @return bool
     */
    public function changeOrder($parameter)
    {
        $log_file = CMF_ROOT."public/wxpay_notify.log";
        log_result($log_file, "【修改订单传参】".":\n".print_r($parameter,true)."\n");

        if(empty($parameter['out_trade_no'])){
            return 1;
        }
        $order_id = $parameter['out_trade_no'];
        $cur_date = time();

        $where = [
            'o.order_id' => ['=', $order_id],
        ];
        //根据订单号获取订单信息
        $order_mdl = new OrderModel();
        $data = $order_mdl->getOrderByField($where);
        if(count($data) <= 0){
            //没有订单
            return 2;
        }
        log_result($log_file, "【订单信息】".":\n".print_r($data->toArray(),true)."\n");

        if($data['order_status'] != 0){
            //非待支付
            return 3;
        }

        $update_data = [
            'id' => $data['id'],
            'order_status' => 1,//已支付
            'payment' => 0,//支付方式(0:微信)
            'pay_no' => $parameter['transaction_id'],//支付流水号
            'pay_time' => $cur_date,//支付时间
            'update_time' => $cur_date,
        ];
        //修改订单
        $result = $order_mdl->editOrder($update_data);
        if(!$result){
            //修改失败
            return 4;
        }

        //记录日志
        $pk = $data['id']; //主键
        $table = 'order';//数据表名
        $content = lang('CHANGE_PAY_ORDER_STATUS', ['orderId' => $order_id]);
        do_log($content, $pk, $table, $cur_date);

        return 5;
    }


    /**
     *查询订单
     */
    public function orderQuery()
    {
        //记录支付信息
        $log_file = CMF_ROOT."public/wxpay_notify.log";

        $_POST["out_trade_no"] = $_SESSION['cur_order_id'];
        //退款的订单号
        if (!isset($_POST["out_trade_no"])){
            $out_trade_no = " ";
        }else{
            $out_trade_no = $_POST["out_trade_no"];
            //使用订单查询接口
            $orderQuery = new \OrderQuery_pub();
            //设置必填参数
            //appid,mch_id,noncestr,sign 已填,无需重复填写
            $orderQuery->setParameter("out_trade_no","$out_trade_no");//商户订单号

            //获取订单查询结果
            $orderQueryResult = $orderQuery->getResult();

            //商户根据实际情况设置相应的处理流程,此处仅作举例
            if ($orderQueryResult["return_code"] == "FAIL") {
                $this->error($out_trade_no,'order/FrontOrder/index');
            }
            elseif($orderQueryResult["result_code"] == "FAIL"){
                $this->error($out_trade_no,'order/FrontOrder/index');
            }
            else{
                //判断交易状态
                switch ($orderQueryResult["trade_state"])
                {
                    case "SUCCESS":
                        //此处应该更新一下订单状态，商户自行增删操作
                        $result = $this->changeOrder($orderQueryResult);
                        switch ($result){
                            case 1:
                                $msg = '订单号为空';
                                break;
                            case 2:
                                $msg = '没有该订单';
                                break;
                            case 3:
                                $msg = '该订单不是待支付状态';
                                break;
                            case 4:
                                $msg = '修改订单状态失败';
                                break;
                            default:
                                $msg = '成功修改订单状态为已支付';
                                break;
                        }
                        log_result($log_file, "【支付信息】".date('Y-m-d H:i:s').":".$msg."\n".print_r($orderQueryResult,true)."\n");

                        $this->success("支付成功！",'order/FrontOrder/index');
                        break;
                    case "REFUND":
                        $this->error("订单转入退款",'order/FrontOrder/index');
                        break;
                    case "NOTPAY":
                        $this->error("订单未支付",'order/FrontOrder/index');
                        break;
                    case "CLOSED":
                        $this->error("关闭订单",'order/FrontOrder/index');
                        break;
                    case "PAYERROR":
                        $this->error("支付失败！".$orderQueryResult["trade_state"],'order/FrontOrder/index');
                        break;
                    default:
                        $this->error("未知失败！".$orderQueryResult["trade_state"],'order/FrontOrder/index');
                        break;
                }
            }
        }
    }


}